// rgSphere.h

#ifndef _RG_SPHERE_H__
#define _RG_SPHERE_H__

//#include "rgObject.h"
//#include "rgVector.h"
//#include "rgRGB.h"
#include <graphics/rgRay.h>
#include <graphics/rgMaterial.h>

namespace rg
{
	class sphere// : public rgObject
	{
	public:
		
		sphere()
		{
			m_position = rgPoint(0, 0, 0);
			m_radius = 10.0f;
		}

		sphere(const rgReal &inX, const rgReal &inY, const rgReal &inZ, const rgReal &inRadius)
		{
			m_position.set(inX, inY, inZ);
			m_radius = inRadius;
		}

		void setSphere( const rgReal &inX, const rgReal &inY, const rgReal &inZ, const rgReal &inRadius)
		{
			m_position.set(inX, inY, inZ);
			m_radius = inRadius;
		}

		inline void setMaterial( material* mat)
		{
			m_pMaterial = mat;
		}

		inline const material* const getMaterial() const
		{
			return m_pMaterial;
		}


		//bool intersect(rgRay& inRay) const;
		inline bool intersect(const rgRay& inRay, rgReal& distance) const
		{
			const rgVector& l = m_position - inRay.m_origin;
			const rgReal s = l * inRay.m_direction;
			const rgReal l2 = l*l;
			const rgReal r2 = m_radius*m_radius;
		    
			// if sphere is behind and ray origin is outside sphere
			if ( s<static_cast<rgReal> (0) && l2 > r2) return rgFALSE; 

			const rgReal m2 = l2 - s*s;

			// if center-ray distance is greater than radius
			if(m2>r2) return rgFALSE;

			const rgReal q = rgFSQRT(r2-m2);

			// if outside sphere get closest, otherwise get furthest point
			if(l2>r2) distance=s-q;
			else distance=s+q;

			//m_lastHit = inRay(inRay.maxL);

			return rgTRUE;
		}

		void getNormal(const rgPoint& inPoint, rgNormal& n) const
		{
			inPoint.getNormal(m_position, n);
		}

	//	bool hitPoint(rgRay *inRay);

		
	public:
		rgPoint m_position;
		rgReal m_radius;
		//rgUint32 m_color;
		material *m_pMaterial;
		//mutable rgPoint m_lastHit;
	};
} // namespace rg
#endif // _RG_SPHERE_H__